#include "decisionTree.h"
#include <assert.h>
#include <sstream>
#include <iostream>

static unsigned int cntr = 0 ;
static unsigned int perturbCntr = 0 ;

/*
 * InvalidGoalException : what (public const member function...)
 * Args        : None
 * Returns     : String(in form of const char*)
 * Throws      : Nothing
 * Defn        :
 *               This exception is thrown when no goal is set and a solution is sought
 */
const char* 
InvalidGoalException::what() const throw()
{
    std::stringstream oss;
    static std::string mystr;
    mystr = "" ;
    oss << "InvalidGoal Exception: No Goal Set." ;
    oss << std::endl ;

    mystr=oss.str();
    return mystr.c_str() ;
}

State::~State()
{
    deleteChildStates() ;
    m_curIdx = -1 ;
    m_itr = m_childStates.end() ;
}

/*
 * State       : initializeChildStateIterator (public non-const member function...)
 * Args        : bool
 *               true  - If all the states are generated and the child states needs to be
 *                       iterated through vector<State*>::iterator
 *               false - If the child are being built equentially, and we still need to iterate the
 *                       child states.
 * Returns     : Nothing
 * Throws      : Nothing
 * Defn        :
 *               Initialize the iterator, in case all the states are generated, set the iterator to childStates.begin()
 *               else set the Curidx as 0
 */
void
State::initializeChildStateIterator(bool allChildStatesGenerated)
{
    if (allChildStatesGenerated) {
        m_itr = m_childStates.begin() ;
	m_curIdx = -1 ;
        return ;
    }
    m_curIdx = 0 ;
}

/*
 * State       : getNextChildState (public non-const member function...)
 * Args        : Nothing
 * Returns     : Child state at current iterator's position.
 * Throws      : Nothing
 * Defn        :
 *               Initialize the iterator, in case all the states are generated, set the iterator to childStates.begin()
 *               else set the Curidx as 0
 */
State*
State::getNextChildState()
{
    if (m_curIdx != -1)
    {
        if (m_childStates.empty() || ((size_t)m_curIdx) >= m_childStates.size())
	    return NULL ;
        return m_childStates[m_curIdx++] ;
    }
    if (m_childStates.empty() || m_itr == m_childStates.end())
        return NULL ;
    State* p_state = *m_itr ;
    ++m_itr ;
    return p_state ;
}

/*
 * State       : perturb (private non-const member function...)
 * Args        : Nothing
 * Returns     : bool - if the perturbation is successful
 * Throws      : Nothing
 * Defn        :
 *               Perturb the item so as to change the usb-state of the state if possible
 *               with perturbed state of the current state, the solution is sought further.
 * 
 * Note        : Its not possible to perturb all the decision tree problem's state. Such problem
 *               would merely return false. To complete the overall solution for current decision-tree
 *               problem at hand , perturb function is defined.
 */
bool
State::perturb()
{
    if (!m_pItem) 
        return false ;
    bool retVal = m_pItem->perturb() ;
    return retVal ;
}

/*
 * State       : deleteChildStates (private non-const member function...)
 * Args        : Nothing
 * Returns     : Nothing
 * Throws      : Nothing
 * Defn        :
 *               Iterate upon all the child states of the current state and destroy them.
 */
void
State::deleteChildStates()
{
    std::vector<State*>::iterator itr = m_childStates.begin() ;
    std::vector<State*>::iterator itrE = m_childStates.end() ;
    for(; itr != itrE; ++itr) {
        State* p_state = *itr ;
        delete p_state ;
    }    
    m_childStates.clear() ;
    m_curIdx = -1 ;
    m_itr = m_childStates.end() ;
}

//virtual
/*
 * DecisionTree  : Destructor
 * Args          : None
 * Returns       : None
 * Throws        : Nothing
 * Defn          :
 *                 Deletes the following :
 *                 1. Delete the model, being constructed and the goal model if any through resteTree call.
 *                 2. Delete state-zero, which recursively deletes all the states below it.
 *                 3. Deletes all the constraints
 *                 4. Deletes all the items contained by the decision tree
 */ 
DecisionTree::~DecisionTree()
{
    resetTree() ;

    delete m_pStateZero ;
    m_pStateZero = NULL ;

    std::vector<Constraint*>::iterator itr = m_constraints.begin() ;
    std::vector<Constraint*>::iterator itrE = m_constraints.end() ;
    for(; itr != itrE; ++itr) {
        Constraint* p_cons = *itr ;
	delete p_cons ;
    }
    m_constraints.clear() ;

    std::set<Item*>::iterator itr1 = m_items.begin() ;
    std::set<Item*>::iterator itr1E = m_items.end() ;
    for(; itr1 != itr1E; ++itr1) {
        Item* p_item = *itr1 ;
	delete p_item ;
    }
    m_items.clear() ;
}

// Will the constrains be satisfied if the state is applied on the model.
/*
 * DecisonTree : willConstraintsBeSatisfied(private non-const member function...)
 * Args        : 
 *               Model curModel  : Current model being constructed.
 *               Model goalModel : Goal model to reach to.
 *               State toState   : The state that needs to be applied to the model.
 * Returns     : bool
 *               true  - If all the constraints(PRE_CONSTRAINT) remains satisfied if the 
 *                       state were to be applied to the model.
 *               false - If any of the constraints(PRE_CONSTRAINT) will fail, if the
 *                       constraint were to be applied on the model.
 * Throws      : Nothing
 * Defn        :
 *               Iterate upon all the constraints in the decisionTree, if the constraint is
 *               pre-constraint and if the state were to be applied on the model and the constraint
 *               remains satisfied, continue with the next constraint else return false.
 */
bool
DecisionTree::willConstraintsBeSatisfied(const Model* p_curModel,
				         const Model* p_goalModel,
				         const State* p_toState) const
{
    std::vector<Constraint*>::const_iterator itr = m_constraints.begin() ;
    std::vector<Constraint*>::const_iterator itrE = m_constraints.end() ;
    for(; itr != itrE; ++itr) {
        const Constraint* p_constraint = *itr ;
        if (p_constraint->isActiveConstraint() && 
	    p_constraint->getConstraintType() == PRE_CONSTRAINT && 
	    !p_constraint->isSatisfied(p_curModel, p_goalModel, p_toState))
            return false ;
    }
    return true ;
}

/*
 * DecisonTree : willConstraintsBeSatisfied(private non-const member function...)
 * Args        : 
 *               Model curModel  : Current model being constructed.
 *               Model goalModel : Goal model to reach to.
 *               State toState   : The state that needs to be applied to the model.
 * Returns     : bool
 *               true  - If all the constraints(POST_CONSTRAINT) remains satisfied, after the 
 *                       state is applied to the model.
 *               false - If any of the constraints(PRE_CONSTRAINT) will fail, after the
 *                       constraint is applied on the model.
 * Throws      : Nothing
 * Defn        :
 *               Iterate upon all the constraints in the decisionTree, if the constraint is
 *               post-constraint and the constraint is satisfied, continue with the next 
 *               constraint. else return false
 */
bool
DecisionTree::areConstraintsSatisfied(const Model* p_curModel,
				     const Model* p_goalModel,
				     const State* p_toState) const
{
    std::vector<Constraint*>::const_iterator itr = m_constraints.begin() ;
    std::vector<Constraint*>::const_iterator itrE = m_constraints.end() ;
    for(; itr != itrE; ++itr) {
        const Constraint* p_constraint = *itr ;
        if (p_constraint->isActiveConstraint() && 
	    p_constraint->getConstraintType() == POST_CONSTRAINT && 
	    !p_constraint->isSatisfied(p_curModel, p_goalModel, p_toState))
            return false ;
    }
    return true ;
}


// Driver Function...
/*
 * DecisonTree : getASolution(public const member function...)
 * Args        : 
 *               Solution states : vector of states, representing the solution.
 *               bool genSta...  : Should all of the child states be generated in one shot while exploring soln.
 * Returns     : bool
 *               true  - If a valid solution is found.
 *               false - If no valid solution is found.
 * Throws      : InvalidGoalException
 * Defn        :
 *               Explores solution using bactracking-approach. To find a solution to the problem at hand, it starts
 *               at zero state, which creates further child states, and the exploration continues through the child states, 
 *               which generates further child states and continues the exploration, till some constraint is failed or
 *               there are no items left to generate any more child state.
 *
 * Algo        :
 *               1. If goal-model is not set throw exception(InvalidGoalModelException), also if zero state is not built return false.
 *               2. Clear the old child states of the zero state.
 *               3. Generate all the child states of the zero state.
 *               4. Iterate upon all the state of the zero state.
 *               5. For every child state from step 4, try to buildASolution.
 *               6. If a solution is found at step 5, return true from this function.
 *               7. if all the states are not generated, generate it further.
 *               8. Continue iteration, through step5.
 *               9. At the end of iteration, return false.
 */
bool
DecisionTree::getASolution(Solution& states, bool genStatesTogether) const
{
    if (!m_pGoalModel) 
        throw InvalidGoalException() ;

    if (!m_pStateZero) 
        return false ;

    m_pStateZero->deleteChildStates() ;
    states.clear() ;

    if (genStatesTogether) 
        (void)generateAllChildStates(states, m_pStateZero) ;
    else 
        (void)generateNextChildState(NULL, states, m_pStateZero) ;

    m_pStateZero->initializeChildStateIterator(genStatesTogether) ;

    State* p_childState = NULL ;
    bool allStatesGenerated = false ;
    cntr = 0 ;
    while((p_childState = m_pStateZero->getNextChildState()))
    {
        if (buildASolution(states, p_childState, genStatesTogether)) {
	    std::cout << "Generated : "<<cntr<< " States before hitting a solution!!!.\n" ;
	    std::cout << "Generated : "<<perturbCntr<< " States(including perturbation) before hitting a solution!!!.\n" ;
            return true ;
        }
        states.clear() ;
        if (!genStatesTogether && !allStatesGenerated) {
 	    if (!generateNextChildState(p_childState, states, m_pStateZero))
                allStatesGenerated = true ;
	}
    }
    assert(states.empty()) ; // Maske sure we have backtracked properly.
    return 0 ;
}

/*
 * DecisonTree : buildASolution(private const member function...)
 * Args        : 
 *               Solution states : vector of states, representing the solution.
 *               State p_state   : current state being explored for solution.
 *               bool genSta...  : Should all of the child states be generated in 
 *                                 one shot while exploring soln.
 * Returns     : bool
 *               true  - If a valid solution is found.
 *               false - If no valid solution is found.
 * Throws      : Nothing
 * Defn        :
 *               Explores solution using bactracking-approach. To find a solution 
 *               to the problem at hand, continue at input state, which creates further 
 *               child states, and the exploration continues through the child states, 
 *               which generates further child states and continues the exploration, till 
 *               some constraint is failed along the way or there are no more items left to 
 *               generate any more child state, or a solution is found.
 *
 * Algo        :
 *               1. Initialize the state to generate a solution, makes the state ready for 
 *                  exploration.
 *               2. Fix the state to generate soolution, if fixing is not possible continue, 
 *                  go to step 10
 *               3. Will all the pre-constraints be satisfied, if the current state is applied 
 *                  to the model, if not go to step 10
 *               4. Apply the state on the model.
 *               5. Are all the post-constraints satisfied, if not,  backtrack state from the 
 *                  model and  go to step 10
 *               6. If after applying model, constraints are satisfied, consider the state as 
 *                  part of solution by collecting it in solution-state vector.
 *               7. If the child states of the state is not generated yet, generate 
 *                  them(together or sequentially, depending upon input flag genStat..)
 *               8. Iterate upon the child-states of the input state and recursively call buildASolution.
 *                  if a solution is found return true.
 *               9. If the solution is still not generated, backtrack the current state from 
 *                  the model, and remove it from solution vector
 *              10. If perturbation is possible, perturb the current state and continue at step 2.
 *              11. If noting worked, delete all the child states of the current state.
 */
bool
DecisionTree::buildASolution(Solution& states, State* p_state, bool genStatesTogether) const
{
    bool stateAppliedOnModel = false ;
    bool allChildStatesGenerated = false ;
    p_state->initiateStateForSolution() ;

    static int depth = 0 ;
    depth++ ;
    cntr++ ;
   
    do
    {
        perturbCntr++ ;
#ifdef __DEBUG__
        std::cout << "Came to Try State with config in build for Solution : " ;
        p_state->printState() ;
#endif         
        if (!p_state->fixStateForSolution()) {
#ifdef __DEBUG__
            std::cout << "Failed to fix state for solution : " ;
            p_state->printState() ;
#endif
            continue ;
        }
        
        if (!willConstraintsBeSatisfied(m_pModel, m_pGoalModel, p_state)) {
#ifdef __DEBUG__
            std::cout << "Application of state not possible, continuing with next perturbed state : " ;
            p_state->printState() ;
#endif            
            p_state->resetStateOriginal() ;
            continue ;
        }

        p_state->applyStateOnModel(m_pModel) ;
#ifdef __DEBUG__
        std::cout << "After Applying state on the model : " ;
        p_state->printState() ;
        std::cout << "Model under cons : \n" ;
        m_pModel->printModel() ;
#endif         

        if (!areConstraintsSatisfied(m_pModel, m_pGoalModel, p_state)) {
            p_state->backtrackState(m_pModel) ;
#ifdef __DEBUG__
            std::cout << "BackTracked , as Post constraint failed for state for solution : " ;
            p_state->printState() ;
            std::cout << "Model Under Cons : \n" ;
            m_pModel->printModel() ;
#endif            
            continue ;
	}
        states.insert(states.end(), p_state) ;

        if (isFinalStateReached()) {
	   depth-- ;
  	   return true ;
	}

        if (!stateAppliedOnModel) {
  	    if (genStatesTogether) {
 	        (void)this->generateAllChildStates(states, p_state) ;
                allChildStatesGenerated = true ;
	    }
            else if (!allChildStatesGenerated) {
	        if(this->generateNextChildState(NULL, states, p_state) == 0 )
		    allChildStatesGenerated = true ;
	    }
	    stateAppliedOnModel = true ;
	}
        
        p_state->initializeChildStateIterator(genStatesTogether) ;
        State* p_childState = NULL ;
        while((p_childState = p_state->getNextChildState()))
        {
#ifdef __DEBUG__
  	    std::cout << cntr << ". About to call another buildASolution at depth"<<depth<<" For State : " ;
	    p_state->printState() ;  
  	    std::cout << "With Child State : " ;
            p_childState->printState() ;
	    std::cout << "Current structure of Model = \n" ;
	    m_pModel->printModel() ;
	    std::cout << "Current Solution state :\n" << getCurSolutionStateStr(states) << std::endl ;
#endif
  	    if (this->buildASolution(states, p_childState, genStatesTogether)) 
                return true ;
	    
            if (!genStatesTogether && !allChildStatesGenerated) {
	        if(generateNextChildState(p_childState, states, p_state) == 0) 
		    allChildStatesGenerated = true ;
	    }
        }
        allChildStatesGenerated = false ;
        p_state->backtrackState(m_pModel) ;
        stateAppliedOnModel = false ;
        p_state->deleteChildStates() ;
#ifdef __DEBUG__
        std::cout << "BackTracked, as no solution could be found through state : " ;
        p_state->printState() ;
        std::cout << "Model Under Cons : \n" ;
        m_pModel->printModel() ;
        int dummy = 0 ;
	if (states.size() == 8)
	    dummy = 1 ;
#endif
          
        states.pop_back() ;
    } while(p_state->perturb() != false) ;

#ifdef __DEBUG__
    std::cout << "Coming out of buildASolution for state : " ;
    p_state->printState()  ;
#endif    
    if (stateAppliedOnModel)
        p_state->deleteChildStates() ;
    depth-- ;
    return false ;
}

/*
 * DecisonTree : getASolution(public const member function...)
 * Args        : 
 *               SolutionCallBackcb : The call-back routine that needs to be called once a solution is found.
 *               bool genSta...     : Should all of the child states be generated in one shot while exploring soln.
 * Returns     : bool
 *               true  - If any valid solution is found.
 *               false - If no valid solution is found.
 * Throws      : InvalidGoalException
 * Defn        :
 *               Explores solution using bactracking-approach. To find a solution to the problem at hand, it starts
 *               at zero state, which creates further child states, and the exploration continues through the child states, 
 *               which generates further child states and continues the exploration, till some constraint is failed or
 *               there are no items left to generate any more child state.
 *
 * Algo        :
 *               1. If goal-model is not set throw exception(InvalidGoalModelException), or if zero-state is not built return false.
 *               2. Clear the old child states of the zero state.
 *               3. Generate all the child states of the zero state.
 *               4. Iterate upon all the state of the zero state.
 *               5. For every child state from step 4, try to buildASolution.
 *               6. If a solution is found at step 5, call the callback function and try other solution, first
 *                  by perturbing the current state and finally by trying other child states of the current state
 *               7. if all the states are not generated, generate it further.
 *               8. Continue iteration, through step5.
 *               9. At the end of iteration, return false.
 */
bool
DecisionTree::getAllSolutions(solutionCallback cb, bool genStatesTogether) const
{
    if (!m_pGoalModel) 
        throw InvalidGoalException() ;

    if (!m_pStateZero) 
        return false ;

    Solution states ;

    m_pStateZero->deleteChildStates() ;
    states.clear() ;
    if (genStatesTogether)
        (void)generateAllChildStates(states, m_pStateZero) ;
    else
        (void)generateNextChildState(NULL, states, m_pStateZero) ;

    m_pStateZero->initializeChildStateIterator(genStatesTogether) ;

    State* p_childState = NULL ;
    bool solnFound = false ;
    while((p_childState = m_pStateZero->getNextChildState()))
    {
        (void)buildAllSolutions(states, p_childState, cb, solnFound, genStatesTogether) ;
        states.clear() ;
        //while(p_childState->perturb()) // Its already being done in buildAllSolutions
        {
	    (void)buildAllSolutions(states, p_childState, cb, solnFound, genStatesTogether) ;
            states.clear() ;
        }
        if(!genStatesTogether)
  	    (void)generateNextChildState(p_childState, states, m_pStateZero) ; 
    }
    assert(states.empty()) ;
    return solnFound ;    
}

/*
 * DecisonTree : buildASolution(private const member function...)
 * Args        : 
 *               Solution states : vector of states, representing the solution.
 *               State p_state   : current state being explored for solution.
 *               SolutionCB cb   : call-back which needs to be called if a solution is found.
 *               bool solnFound  : set this flag true if any solution is found.
 *               bool genSta...  : Should all of the child states be generated in 
 *                                 one shot while exploring soln.
 * Returns     : bool
 *               true  - If a valid solution is found.
 *               false - If no valid solution is found.
 * Throws      : Nothing
 * Defn        :
 *               Explores solution using bactracking-approach. To find a solution 
 *               to the problem at hand, continue at input state, which creates further 
 *               child states, and the exploration continues through the child states, 
 *               which generates further child states and continues the exploration, till 
 *               some constraint is failed along the way or there are no more items left to 
 *               generate any more child state, or a solution is found.
 *
 * Algo        :
 *               1. Initialize the state to generate a solution, makes the state ready for 
 *                  exploration.
 *               2. Fix the state to generate soolution, if fixing is not possible continue, 
 *                  go to step 10
 *               3. Will all the pre-constraints be satisfied, if the current state is applied 
 *                  to the model, if not go to step 10
 *               4. Apply the state on the model.
 *               5. Are all the post-constraints satisfied, if not,  backtrack state from the 
 *                  model and  go to step 10
 *               6. If after applying model, constraints are satisfied, consider the state as 
 *                  part of solution by collecting it in solution-state vector.
 *               7. If the child states of the state is not generated yet, generate 
 *                  them(together or sequentially, depending upon input flag genStat..)
 *               8. Iterate upon the child-states of the input state and recursively call buildAllSolutions.
 *                  if a solution is found, call the callback routine with solution.
 *               9. If the solution is still not generated, backtrack the current state from 
 *                  the model, and remove it from solution vector
 *              10. If perturbation is possible, perturb the current state and continue at step 2.
 *              11. If nothing worked, delete all the child states of the current state.
 */
bool
DecisionTree::buildAllSolutions(Solution& states,
                                State* p_state, solutionCallback cb,
                                bool& solutionFound, bool genStatesTogether) const
{
    bool stateAppliedOnModel = false ;
    bool allChildStatesGenerated = false ;
    p_state->initiateStateForSolution() ;
    static int depth = 0 ;
    depth++ ;
    cntr++ ;
    do
    {
        perturbCntr++ ;
        if (!willConstraintsBeSatisfied(m_pModel, m_pGoalModel, p_state)) 
            continue ;

        if (!p_state->fixStateForSolution())
	    continue ;

        if (!willConstraintsBeSatisfied(m_pModel, m_pGoalModel, p_state)) {
            p_state->resetStateOriginal() ;
	    continue ;
	}

        p_state->applyStateOnModel(m_pModel) ;

	if (!areConstraintsSatisfied(m_pModel, m_pGoalModel, p_state)) {
	    p_state->backtrackState(m_pModel) ;
	    continue ;
	}

        states.insert(states.end(), p_state) ;
        
        if (isFinalStateReached()) {
            cb(states) ;
            if (!solutionFound)
                solutionFound = true ;
        }
         
        if (!stateAppliedOnModel) {
  	    if (genStatesTogether) {
  	        (void)generateAllChildStates(states, p_state) ;
                allChildStatesGenerated = true ;
	    }
	    else
	        (void)generateNextChildState(NULL, states, p_state) ;
	    stateAppliedOnModel = true ;
	}        
        
        p_state->initializeChildStateIterator(genStatesTogether) ;
        State* p_childState = NULL ;
        while((p_childState = p_state->getNextChildState()))
        {
  	    this->buildAllSolutions(states, p_childState, cb, solutionFound, genStatesTogether) ;
            if (!genStatesTogether && !allChildStatesGenerated)
  	        (void)generateNextChildState(p_childState, states, p_state) ; 
        }
        allChildStatesGenerated = false ;
        p_state->backtrackState(m_pModel) ;
        stateAppliedOnModel = false ;
        p_state->deleteChildStates() ;
        states.pop_back() ;
    } while(p_state->perturb()) ;
    if (stateAppliedOnModel)
        p_state->deleteChildStates() ;    
    return solutionFound ;
}

/*
 * State       : setGoalModel (public non-const member function...)
 * Args        : Model p_model : Model which needs to be set as goalModel
 * Returns     : Nothing
 * Throws      : Nothing
 * Defn        :
 *               Sets the input model as goal model, also set the blank soln model with the same traits
 *               as goal model through getNewModelWithSelfTraits of Model.
 */
void
DecisionTree::setGoalModel(Model* p_model)
{
    if (!p_model)
        return ;
    m_pGoalModel = p_model ;
    m_pModel = m_pGoalModel->getNewModelWithSelfTraits() ;
}

/*
 * State       : getConstraint (public const member function...)
 * Args        : strring name : name of the constraint being searched
 * Returns     : Constraint object in the constraints collection whose name matches the input string.
 * Throws      : Nothing
 * Defn        :
 *               Iterate upon all the constraints and search for the one whose name matches input string.
 */
Constraint*
DecisionTree::getConstraint(const std::string& name) const
{
    std::vector<Constraint*>::const_iterator itr = m_constraints.begin() ;
    std::vector<Constraint*>::const_iterator itrE = m_constraints.end() ;

    for(; itr != itrE; ++itr) {
        Constraint* p_cons = *itr ;
        if (p_cons->getConstraintName() == name)
	    return p_cons ;
    }
    return NULL ;
}

/*
 * DecisonTree : getActiveConstraint (public const member function...)
 * Args        : vector of constraints, which will be populated with constraints which are active
 * Returns     : Nothing
 * Throws      : Nothing
 * Defn        :
 *               Iterate upon all the constraints and collect the active ones in input vector
 */
void
DecisionTree::getActiveConstraints(std::vector<Constraint*>& constraints) const
{
    std::vector<Constraint*>::const_iterator itr = m_constraints.begin() ;
    std::vector<Constraint*>::const_iterator itrE = m_constraints.end() ;

    for(; itr != itrE; ++itr) {
        Constraint* p_cons = *itr ;
        if (p_cons->isActiveConstraint())
	    constraints.push_back(p_cons) ;
    }
    return ;
}

/*
 * State       : initializeModel (public const member function...)
 * Args        : Nothing
 * Returns     : bool (always true for now)
 * Throws      : Nothing
 * Defn        :
 *               Clean up the solution and goalModel by destroying them, so that a fresh problem
 *               can seek solution through the infrastructure
 * ToDo        : Make the return value more meaningful or make the return type as void.
 */
bool
DecisionTree::initializeModel()
{
    resetTree() ;
    return true ;
}

/*
 * DecisionTree : resetTree (private non-const member function...)
 * Args         : Nothing
 * Returns      : Nothing
 * Throws       : Nothing
 * Defn         :
 *                Clean up the solution and goalModel by destroying them, so that a fresh problem
 *                can seek solution through the infrastructure
 */
void
DecisionTree::resetTree()
{
    if (m_pModel)
        delete m_pModel ;

    m_pModel = NULL ;
    m_pGoalModel = NULL ;
}


